// updateChildren.js
import createElement from './createElement'
import patchVnode from './patchVnode'

// 判断是否是同一个虚拟节点
function checkSameVnode(a, b) {
  return a.sel === b.sel && a.key === b.key
}
export default function updateChildren(parentElm, oldCh, newCh) {
  // console.log('我是updateChildren')
  // console.log(oldCh, newCh)
  let oldStartIdx = 0 // 旧前
  let newStartIdx = 0 // 新前
  let oldEndIdx = oldCh.length - 1 // 旧后
  let newEndIdx = newCh.length - 1 // 新后
  let oldStartVnode = oldCh[oldStartIdx] // 旧前节点
  let oldEndVnode = oldCh[oldEndIdx] // 旧后节点
  let newStartVnode = newCh[newStartIdx] // 新前节点
  let newEndVnode = newCh[newEndIdx] // 新后节点
  let keyMap = null
  let none = [null,undefined]
  // 开始循环
  while(oldStartIdx<= oldEndIdx && newStartIdx <= newEndIdx){
    // 旧前小于旧后   新前小于新后
    //  过滤无数据的点
    console.log("vvvv")
    if(none.includes(oldStartVnode)){
      oldStartVnode = oldCh[++oldStartIdx]
    }else if(none.includes(oldEndVnode)){
      oldEndVnode = oldCh[--oldEndIdx]
    }else if(none.includes(newStartVnode)){
      newStartVnode = newCh[++newStartIdx]
    }else if(none.includes(newEndVnode)){
      newEndVnode = newCh[--newEndIdx]
    }else if(checkSameVnode(oldStartVnode,newStartVnode)){
      // 1命中节点  新前和旧前
      console.log('1.命中新前和旧前!')
      patchVnode(oldStartVnode,newStartVnode)
      console.log(oldStartVnode,newStartVnode)
      oldStartVnode = oldCh[++oldStartIdx]
      newStartVnode = newCh[++newStartIdx]
    }else if(checkSameVnode(oldEndVnode,newEndVnode)){
      // 2旧后和旧前
      console.log('2.命中旧后和旧前!')
      patchVnode(oldEndVnode,newEndIdx)
      oldEndVnode = oldCh[--oldEndIdx]
      newEndVnode = newCh[--newEndIdx]
    }else if(checkSameVnode(newEndVnode,oldStartVnode)){
      console.log('3.命中新后和旧前!')
      console.log(newEndVnode,oldStartVnode)

      patchVnode(oldStartVnode,newEndVnode)
      parentElm.insertBefore(oldStartVnode.elm, oldEndVnode.elm.nextSibling)
      newEndVnode = newCh[--newEndIdx]
      oldStartVnode = oldCh[++oldStartIdx]
    }else if(checkSameVnode(newStartVnode,oldEndVnode)){
      console.log('4.命中新前和旧后')
      console.log(oldEndVnode,newStartVnode)

      patchVnode(newStartVnode,oldEndVnode)
      parentElm.insertBefore(oldEndVnode.elm, oldStartVnode.elm)
      newStartVnode = newCh[--newStartIdx]
      oldEndVnode = oldCh[++oldEndIdx]
    }else{
      console.log("都没匹配上")
      // 四种命中都没有找到,支座keyMap 缓存
      if(!keyMap){
        keyMap = {}
        for(let i = oldStartIdx;i<=oldEndIdx;i++){
          const key = oldCh[i].key
          if(key!==undefined){
            keyMap[key] = i
          }
        }
      }
      // 寻找当前这项 newStartIdx 这项在keyMap中映射的序号
      const idxInOld = keyMap[newStartVnode.key]
      // 拿着新虚拟节点的额key去map映射中去寻找  如果说没找到  说明这个节点是新的  找到的话说明这个节点是旧的
      if(idxInOld===undefined){
        // 新的直接添加就行
        parentElm.insertBefore(createElement(newStartVnode),oldStartVnode.elm)
      }else{
        // 此时说明并不是全新的 
        const elmToMove = oldCh[idxInOld]
        console.log('匹配上了',elmToMove)
        patchVnode(elmToMove,newStartVnode)
        //这项已经处理完了  可以将其设置为 undefined
        oldCh[idxInOld] = undefined
        parentElm.insertBefore(elmToMove.elm,oldStartVnode.elm)

      }
      // 至于这里为什么不改变旧的  是因为不让数组打乱    赋值为undefined到时候会自动跳过
      newStartVnode = newCh[++newStartIdx]
    }
    // console.log("while循环内的下标",oldStartIdx,oldEndIdx,newStartIdx,newEndIdx)
  }
  // console.log(oldStartIdx,oldEndIdx,newStartIdx,newEndIdx)
  // while循环结束后  看还有没有剩余
  if(newStartIdx <= newEndIdx){
    console.log('新节点有剩余!')
    // 新虚拟dom还有 将newStartIdx 到newEndIdx之间的虚拟dom生成为真实dom并插入到 已匹配的之后
    for(let i = newEndIdx;i<=newEndIdx;i++){
      parentElm.insertBefore(createElement(newCh[i]),oldCh[oldEndIdx].elm.nextSibing)
    }
  }else if(oldStartIdx <= oldEndIdx){
    console.log('旧节点有剩余!')
    for(let i = oldStartIdx;i<=oldEndIdx;i++){
      console.log(oldCh)
      console.log(oldStartIdx,oldEndIdx)
      if(oldCh[i]){
        parentElm.removeChild(oldCh[i].elm)
      }
    }
  }

}